package natappvip.liujinliang.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import natappvip.liujinliang.common.ResponseCode;
import natappvip.liujinliang.model.FileEle;

/**
 * @ClassName:  FileHandler   
 * @Despt: 封装了基本的I/O流操作 
 * @Auth: Liujinliang 
 * @Date: 2018年7月24日 下午10:49:44
 */
public class FileHandler {
	
	private static Logger logger = LoggerFactory.getLogger(FileHandler.class);
	
	/**
	 * @Title: save   
	 * @Despt: 从src到dest  
	 * @param: @param src
	 * @param: @param dest
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int save(Reader src, Writer dest) {
		try(Reader input = src;Writer output = dest) {
			char[] data = new char[1024];
			int length = -1;
			/* 读取文件 */
			while ((length = input.read(data)) != -1) {
				/* 写入到输出流 */
				output.write(data, 0, length);
			}
		} catch (IOException e) {
			logger.info("错误信息:{}", e.getMessage());
		}
		return 0;
	}
	
	/**
	 * @Title: save   
	 * @Despt: 从src到dest   
	 * @param: @param src
	 * @param: @param dest
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int save(InputStream src, OutputStream dest) {
		
		try {
			save(new InputStreamReader(src, PropertiesUtil.getProperty("charset")), new OutputStreamWriter(dest, PropertiesUtil.getProperty("charset")));
		} catch (UnsupportedEncodingException e) {
			logger.info("\"UTF-8\"字符编码不支持");
		}
		
		return 0;
	}
	
	/**
	 * @Title: record   
	 * @Despt: 记录文件存储的信息实体类 FileEle到文件fileName 
	 * @param: @param ele
	 * @param: @param fileName
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int record(FileEle ele, String fileName) {
		
		try {
			FileHandler.save(new StringReader(ele.toString()+ "\r\n"), new FileWriter(fileName, true));
		} catch (IOException e1) {
			logger.info("【文件记录】I/O异常");
		}
		
		return 1;
	}
	
	/**
	 * @Title: getSize   
	 * @Despt: 获取InputStream的转化为字符串size  
	 * @param: @param fis
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int getSize(InputStream fis) {
		return fis.toString().length();
	}
	
	/**
	 * @Title: record   
	 * @Despt: 记录文件存储的信息到文件fileName    
	 * @param: @param ele
	 * @param: @param fileName
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int record(String ele, String fileName) {
		
		try {
			FileHandler.save(new StringReader(ele+ "\r\n"), new FileWriter(fileName, true));
		} catch (IOException e1) {
			logger.info("【文件记录】I/O异常");
		}
		
		return 1;
	}
	
	/**
	 * @Title: createMultilevelDirectory   
	 * @Despt: 在根目录rootPath下创建多级目录   
	 * @param: @param directories
	 * @param: @param rootPath
	 * @param: @return      
	 * @return: File      
	 * @throws
	 */
	public static File createMultilevelDirectory(String[] directories,String rootPath) {
		
		/* 判断是否不需要创建目录 */
        if (directories.length == 0) {
            return null;
        }
        
        File root = new File(rootPath);
        for (int i = 0; i < directories.length; i++) {
        	
            File directory = new File(root, directories[i]);
            
            /* 目录不存在则创建新目录 */
            if (!directory.exists()) {
            	directory.mkdir();
            }
            
            root = directory;
        }
        return root;
	}
	
	/**
	 * @Title: OutputStream2ByteArray   
	 * @Despt: 从ByteArrayOutputStream到byte[]  
	 * @param: @param output
	 * @param: @return      
	 * @return: byte[]      
	 * @throws
	 */
	public static byte[] OutputStream2ByteArray (OutputStream output) {
		return ((ByteArrayOutputStream)output).toByteArray();
	}
	
	/**
	 * @Title: getFilesByUUID   
	 * @Despt: 根据id获取两级目录下的所有文件  
	 * @param: @param id
	 * @param: @return      
	 * @return: File[]      
	 * @throws
	 */
	public static File[] getFilesByUUID(String id) {
		/*
		 * 获取根目录
		 */
		String rootName = new File("").getAbsolutePath();
		
		/*
		 * 获取目标目录
		 */
		File fileDirectory = new File(rootName + "\\temp\\" + id.substring(0, 2) + "\\" + id.substring(2, 4));
		
		/*
		 * 获取目录下文件
		 */
		File TrxFiles[] = fileDirectory.listFiles();
		
		return TrxFiles;
	}
	
	/**
	 * @Title: getFile   
	 * @Despt: 根据uuid获取文件 
	 * @param: @param id
	 * @param: @return      
	 * @return: File      
	 * @throws
	 */
	public static File getFile(String id) {
		
		/* 项目根目录获取 */
		String rootPath = new File("").getAbsolutePath();
		
		/* 根据UUID递归创建目录 */
		String[] dires = {"temp", id.substring(0, 2), id.substring(2, 4)}; 
		
		File filePath = createMultilevelDirectory(dires, rootPath);
		
		/* 根据UUID创建文件 */
		File file = new File(filePath, id);
		
		/* 文件不存在则创建新文件 */
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				logger.info("【根据UUID创建文件】{}文件创建失败,失败信息:{}", file.getName(), e.getMessage());
			}
		}
		
		return file;
	}
	
	/**
	 * @Title: delRecord   
	 * @Despt: 从记录文件存储的元信息文件中删除uuid的条目   
	 * @param: @param uuid
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int delRecord(String uuid) {
		
		File file = new File(PropertiesUtil.getProperty("mdata"));   // 原记录文件，最后会被删除
		File file2 = new File("mdata-new.txt");	// 被删除uuid=id文件信息元后的记录的文件 
		String line = null;
		   
		try ( BufferedReader reader = new BufferedReader(new FileReader(file));
			  PrintWriter writer = new PrintWriter(file2) ) {
			while ((line = reader.readLine()) != null) {   
				writer.println(line);   
				writer.flush();   
			}
		} catch (IOException e) {
			logger.info("【删除文件】I/O异常");
			return -1;
		}   
		   
		file.delete();   
		file2.renameTo(file);  
		
		return 0;
	}

	/**
	 * @Title: delFile   
	 * @Despt: 删除uuid为文件名的文件 
	 * @param: @param uuid
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int delFile(String uuid) {
		int flag = -1;
		File[] TrxFiles = getFilesByUUID(uuid);
        for(File curFile:TrxFiles ){	// 遍历文件
        	if (curFile.getName().equals(new String(uuid))) {		// 命中文件
        		curFile.delete(); 	// 删除文件
        		flag = 0;
        	}
        }
		return flag;
	}
	
	/**
	 * @Title: copy   
	 * @Despt: 从Reader到Writer，用来文件拷贝   
	 * @param: @param reader
	 * @param: @param writer      
	 * @return: void      
	 * @throws
	 */
	public static void copy(Reader reader, Writer writer) {
		String line = null;
		try(
				BufferedReader bufferedReader = new BufferedReader(reader); 
				BufferedWriter bufferedWriter = new BufferedWriter(writer)) {
			
			while ((line = bufferedReader.readLine()) != null) {
				bufferedWriter.write(line);
			}
		} catch (IOException e) {
			logger.info("错误信息:{}", e.getMessage());
		}
	}
	
	/**
	 * @Title: getMap   
	 * @Despt: 封装文件的文件名、文件大小、文件内容到Map中  
	 * @param: @param fileName
	 * @param: @return      
	 * @return: Map<String,Object>      
	 * @throws
	 */
	public static Map<String, Object> getMap(String fileName) {
		if (checkFile(fileName) != 0) {
			return null;
		}
		File file = new File(fileName);
		Map<String, Object> map = new HashMap<>(3);
		map.put("name", fileName);
		map.put("size", file.length());
		map.put("content", getOutputStream(fileName).toByteArray());
		return map;
	}
	
	/**
	 * @Title: getOutputStream   
	 * @Despt: 把文件写入到字节数组流   
	 * @param: @param fileName
	 * @param: @return      
	 * @return: ByteArrayOutputStream      
	 * @throws
	 */
	public static ByteArrayOutputStream getOutputStream(String fileName) {
		try(FileInputStream input = new FileInputStream(fileName);
				ByteArrayOutputStream output = new ByteArrayOutputStream()) {
			save(input, output);
			return output;
		} catch (FileNotFoundException e) {
			logger.info("错误信息:{}", e.getMessage());
		} catch (IOException e) {
			logger.info("错误信息:{}", e.getMessage());
		}
		return null;
	}
	
	/**
	 * @Title: checkFile   
	 * @Despt: 检查文件是否存在   
	 * @param: @param fileName
	 * @param: @return      
	 * @return: int      
	 * @throws
	 */
	public static int checkFile(String fileName) {
		File file = new File(fileName);
		if ( ! file.exists()) {
			System.out.println("您的文件不存在，请检查路径是否输入有误");
			return ResponseCode.ERROR.getCode();
		}
		return ResponseCode.SUCCESS.getCode();
	}
	
	/**
	 * @Title: getByteArray   
	 * @Despt: 以字节数组方式获取输入流   
	 * @param: @param inputStream
	 * @param: @return      
	 * @return: byte[]      
	 * @throws
	 */
	public static byte[] getByteArray(InputStream inputStream) {
		try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream();) {
			save(inputStream, outputStream);
			return outputStream.toByteArray();
		} catch (IOException e) {
			logger.info("byte[]获取失败，错误信息:{}", e.getMessage());
		}
		return null;
	}

}
